
#include "HiBoost.Data.h"

using namespace hi_boost;

//// [*] hi_boost::CBasicNodeInstance
//
//CBasicNodeInstance::CBasicNodeInstance()
//{
//	Clear(true);
//}
//void CBasicNodeInstance::Clear(bool fIsMissing)
//{
//	x = y = rotation = 0.0;
//	inferance_scale = 1.0;
//	this->fIsMissing = fIsMissing;
//}
//
//void CBasicNodeInstance::Enable(double x, double y, double rotation, double inferance_scale)
//{
//	this->x = x;
//	this->y = y;
//	this->rotation = rotation;
//	this->inferance_scale = inferance_scale;
//	this->fIsMissing = false;
//}
//
//void CBasicNodeInstance::Disable()
//{
//	Clear(true);
//}
//
//// [*] hi_boost::CNodeInstanceSet
//
//int CNodeInstanceSet::InputAnnotationFromStream(istream& inStream, int NodeAmount)
//{
//	int ret;
//	CBasicNodeInstance tInstance;
//	int i, ii, ti;
//	double tx, ty;
//
//	this->NodeAmount = NodeAmount;
//	tInstance.Disable();
//	List_PerNodeInstance.Resize(NodeAmount); List_PerNodeInstance.Fill(tInstance);
//	if (!(inStream>>ii)) return 0;
//	ret = 0;
//	for ( i = 0; i < ii; ++i )
//	{
//		if (!(inStream>>ti>>tx>>ty)) break;
//		if (ti<0 || ti>=NodeAmount) continue;
//		tInstance.Enable(tx, ty, 0.0, 1.0);
//		if (List_PerNodeInstance.pElement[ti].fIsMissing) ++ret;
//		List_PerNodeInstance.pElement[ti] = tInstance;
//	}
//	return ret;
//}
//
//int CNodeInstanceSet::GetInstanceAmount() const
//{
//	int ret = NodeAmount;
//	for ( int i = 0; i < NodeAmount; ++i )
//		if (List_PerNodeInstance.pElement[i].fIsMissing) --ret;
//	return ret;
//}
//
////void CNodeInstanceSet::DoTransformation(const CCoordinateTransformer* pCoordinateTransformer)
////{
////	int i;
////	for ( i = 0; i < NodeAmount; ++i )
////	{
////		CBasicNodeInstance& CurrentInstance = List_PerNodeInstance.pElement[i];
////		if (!CurrentInstance.fIsMissing)
////			pCoordinateTransformer->Work(CurrentInstance.x, CurrentInstance.y, CurrentInstance.x, CurrentInstance.y);
////	}
////}
//
//void CNodeInstanceSet::DoTransformation(const CZoomConfig& ZoomConfig)
//{
//	int i;
//	for ( i = 0; i < NodeAmount; ++i )
//	{
//		CBasicNodeInstance& CurrentInstance = List_PerNodeInstance.pElement[i];
//		if (!CurrentInstance.fIsMissing)
//			ZoomConfig.Work(CurrentInstance.x, CurrentInstance.y, CurrentInstance.x, CurrentInstance.y);
//	}
//}
//
//// [*] hi_boost::CGroundTruthAnnotation
//
//void CGroundTruthAnnotation::LoadFromFile(string strFN_Annotation, int NodeAmount)
//{
//	ifstream inFile(strFN_Annotation.c_str());
//	inFile>>ImageIndex>>ObjectIndex>>fIsFlipped;
//	this->InputAnnotationFromStream(inFile, NodeAmount);
//	inFile.clear();
//	inFile.close();
//}
//
//bool CGroundTruthAnnotation::operator < (const CGroundTruthAnnotation& AnotherInstance) const
//{
//	if (ImageIndex != AnotherInstance.ImageIndex) return ImageIndex < AnotherInstance.ImageIndex;
//	if (ObjectIndex != AnotherInstance.ObjectIndex) return ObjectIndex < AnotherInstance.ObjectIndex;
//	return (fIsFlipped < AnotherInstance.fIsFlipped);
//}

// [*] CHiBoostNodeInstanceBoxSet

CHiBoostNodeInstanceBoxConfig CHiBoostNodeInstanceBoxSet::s_Config;

void CHiBoostNodeInstanceBoxSet::InitLeafInstanceSet(const double* pX, const double* pY)
{
	Leaf_X_List.Clear(); Leaf_X_List.PushBack(pX, s_Config.pTree->LeafNodeAmount);
	Leaf_Y_List.Clear(); Leaf_Y_List.PushBack(pY, s_Config.pTree->LeafNodeAmount);
	RefreshLeafInstanceSet();
}

void CHiBoostNodeInstanceBoxSet::InitLeafInstanceSet(const CSimpleTypeArray<double>& Leaf_X_List, const CSimpleTypeArray<double>& Leaf_Y_List)
{
	InitLeafInstanceSet(Leaf_X_List.pElement, Leaf_Y_List.pElement);
}

void CHiBoostNodeInstanceBoxSet::RefreshLeafInstanceSet()
{
	int j;
	const double* pX = Leaf_X_List.pElement;
	const double* pY = Leaf_Y_List.pElement;

	Center_X = Center_Y = 0.0;
	for ( j = 0; j < s_Config.pTree->LeafNodeAmount; ++j, ++pX, ++pY )
	{
		Center_X += *pX;
		Center_Y += *pY;
		if (j==0 || *pX<All_BoundingBox.x) All_BoundingBox.x = *pX;
		if (j==0 || *pX>All_BoundingBox.w) All_BoundingBox.w = *pX;
		if (j==0 || *pY<All_BoundingBox.y) All_BoundingBox.y = *pY;
		if (j==0 || *pY>All_BoundingBox.h) All_BoundingBox.h = *pY;
	}
	Center_X /= s_Config.pTree->LeafNodeAmount;
	Center_Y /= s_Config.pTree->LeafNodeAmount;
	All_BoundingBox.w -= All_BoundingBox.x;
	All_BoundingBox.h -= All_BoundingBox.y;
}

const double* CHiBoostNodeInstanceBoxSet::GetPtrLeaf_X() const
{
	return Leaf_X_List.pElement;
}

const double* CHiBoostNodeInstanceBoxSet::GetPtrLeaf_Y() const
{
	return Leaf_Y_List.pElement;
}

void CHiBoostNodeInstanceBoxSet::ComputeNodeCenter(double& DstX, double& DstY, int NodeIndex) const
{
	DstX = DstY = 0.0;
	if (NodeIndex<0 || NodeIndex>=s_Config.pTree->NodeAmount) return;
	const and_or_tree::CAbstractNode* pNode = s_Config.pTree->GetNode(NodeIndex);
	int i, ii;
	const int* qi = pNode->GetPtrLeafIndexOfSubTreeLeafNode();
	const double* qx = Leaf_X_List.pElement;
	const double* qy = Leaf_Y_List.pElement;
	ii = pNode->GetSubTreeLeafNodeAmount();
	for ( i = 0; i < ii; ++i, ++qi )
	{
		DstX += qx[*qi];
		DstY += qy[*qi];
	}
	DstX /= ii;
	DstY /= ii;
}

void CHiBoostNodeInstanceBoxSet::ComputeNodeBoundingBox(CRectBox<double>& DstBoundingBox, int NodeIndex) const
{
	DstBoundingBox.x = DstBoundingBox.y = 0.0;
	DstBoundingBox.w = DstBoundingBox.h = 0.0;
	if (NodeIndex<0 || NodeIndex>=s_Config.pTree->NodeAmount) return;
	const and_or_tree::CAbstractNode* pNode = s_Config.pTree->GetNode(NodeIndex);
	double tt;
	int i, ii;
	const int* qi = pNode->GetPtrLeafIndexOfSubTreeLeafNode();
	const double* qx = Leaf_X_List.pElement;
	const double* qy = Leaf_Y_List.pElement;
	ii = pNode->GetSubTreeLeafNodeAmount();

	for ( i = 0; i < ii; ++i, ++qi )
	{
		if (i==0 || qx[*qi]<DstBoundingBox.x) DstBoundingBox.x = qx[*qi];
		if (i==0 || qx[*qi]>DstBoundingBox.w) DstBoundingBox.w = qx[*qi];
		if (i==0 || qy[*qi]<DstBoundingBox.y) DstBoundingBox.y = qy[*qi];
		if (i==0 || qy[*qi]>DstBoundingBox.h) DstBoundingBox.h = qy[*qi];
	}
	DstBoundingBox.w -= DstBoundingBox.x;
	DstBoundingBox.h -= DstBoundingBox.y;

	tt = All_BoundingBox.w * s_Config.MinBoundingBoxRelativeScale_X - DstBoundingBox.w;
	if (tt > EPS)
	{
		DstBoundingBox.x -= tt * 0.5;
		DstBoundingBox.w += tt;
	}
	tt = All_BoundingBox.h * s_Config.MinBoundingBoxRelativeScale_Y - DstBoundingBox.h;
	if (tt > EPS)
	{
		DstBoundingBox.y -= tt * 0.5;
		DstBoundingBox.h += tt;
	}
}

void CHiBoostNodeInstanceBoxSet::ComputeNodeBoundingBoxCenter(double& DstX, double& DstY, int NodeIndex) const
{
	CRectBox<double> bbox;
	ComputeNodeBoundingBox(bbox, NodeIndex);
	DstX = bbox.x + bbox.w * 0.5;
	DstY = bbox.y + bbox.h * 0.5;
}

void CHiBoostNodeInstanceBoxSet::DoTRS(const C_TRSable_Image::CParameters& trsConfig)
{
	int i;
	
	for ( i = 0; i < s_Config.pTree->LeafNodeAmount; ++i )
		trsConfig.ComputeNewPosition(Leaf_X_List.pElement[i], Leaf_Y_List.pElement[i], Leaf_X_List.pElement[i], Leaf_Y_List.pElement[i]);
	RefreshLeafInstanceSet();
}

void CHiBoostNodeInstanceBoxSet::DoTransformation(const CCoordinateTransformer* pCoordinateTransformer)
{
	int i;
	for ( i = 0; i < s_Config.pTree->LeafNodeAmount; ++i )
		pCoordinateTransformer->Work(Leaf_X_List.pElement[i], Leaf_Y_List.pElement[i], Leaf_X_List.pElement[i], Leaf_Y_List.pElement[i]);
	RefreshLeafInstanceSet();
}

void CHiBoostNodeInstanceBoxSet::DoTransformation(const CImageTransformation& ImageTransformation)
{
	DoTransformation(&ImageTransformation);
}

// [*] CHiBoostGroundTruth

void CHiBoostGroundTruth::myInit(string strFN_GroundTruth)
{
	//InitConfig(pConfig);
	ifstream inFile_GT(strFN_GroundTruth.c_str());
	int j, t, o;
	double x, y;
	inFile_GT>>MaterialIndex>>ObjectIndex>>fIsFlipped>>o;
	Leaf_X_List.Resize(s_Config.pTree->LeafNodeAmount); Leaf_X_List.Fill(0.0);
	Leaf_Y_List.Resize(s_Config.pTree->LeafNodeAmount); Leaf_Y_List.Fill(0.0);
	Center_X = Center_Y = 0.0;
	for ( j = 0; j < o; ++j )
	{
		inFile_GT>>t>>x>>y;
		Leaf_X_List.pElement[t] = x;
		Leaf_Y_List.pElement[t] = y;
	}
	inFile_GT.clear();
	inFile_GT.close();
	RefreshLeafInstanceSet();
}

//// [*] CHiBoostNodeContextConfig::CNode
//
//bool CHiBoostNodeContextConfig::CNode::InputFromStream(istream& inStream)
//{
//	//char strTemp[10001];
//	//const char* pc;
//
//	if (inStream>>xScale>>yScale>>xOffset>>yOffset>>Context_W>>Context_H)
//	{
//		inStream>>CellWidth>>CellHeight;
//		//inStream.getline(strTemp, 10000);
//		//for ( pc = strTemp; (*pc==' ' || *pc=='\t' || *pc=='\r' || *pc=='\n'); ++pc );
//		//strFN_ShapePatterns = pc;
//		return true;
//	}
//	return false;
//}
//
//// [*] CHiBoostNodeContextConfig
//
//CHiBoostNodeContextConfig::CHiBoostNodeContextConfig()
//{
//	Clear();
//}
//
//void CHiBoostNodeContextConfig::Clear()
//{
//	GlobalObject.xScale = GlobalObject.yScale = 1.0;
//	GlobalObject.xOffset = GlobalObject.yOffset = 0.5;
//	Size = 0;
//	HeaderList.Clear();
//	Data.Clear();
//}
//
//void CHiBoostNodeContextConfig::myInit(string strFN_ScaleLevelConfig)
//{
//	ifstream inFile(strFN_ScaleLevelConfig.c_str());
//
//	Clear();
//	int i;
//	CNode tNode;
//
//	GlobalObject.InputFromStream(inFile);
//	while ((inFile>>i) && (i>=-1))
//	{
//		if (!tNode.InputFromStream(inFile)) break;
//		++Size;
//		HeaderList.PushBack(i);
//		Data.PushBack(tNode);
//	}
//
//	inFile.clear();
//	inFile.close();
//}
//
//const CHiBoostNodeContextConfig::CNode& CHiBoostNodeContextConfig::GetDataForNode(int NodeIndex) const
//{
//	int zz = (int)(upper_bound(HeaderList.Begin(), HeaderList.End(), NodeIndex) - HeaderList.Begin()) - 1;
//	if (zz < 0) zz = 0;
//	return Data.pElement[zz];
//}
//
////void CHiBoostNodeContextConfig::GetStdPartContextSize(int& Dst_W, int& Dst_H, int NodeIndex) const
////{
////	const CNode& nd = GetDataForNode(NodeIndex);
////	Dst_W = nd.Context_W;
////	Dst_H = nd.Context_H;
////}
//
////void CHiBoostNodeContextConfig::GetStdBoxForNodeInstance(
////	double& DstCenterX, double& DstCenterY,
////	double CenterX, double CenterY, int NodeIndex,
////	double InversedScaleX, double InversedScaleY)
////{
////	const CNode& tc = GetDataForNode(NodeIndex);
////	CRectBox<double> tbox;
////	tbox.w = tc.Context_W / tc.xScale / InversedScaleX;
////	tbox.h = tc.Context_H / tc.yScale / InversedScaleY;
////	tbox.x = CenterX - tbox.w * 0.5;
////	tbox.y = CenterY - tbox.h * 0.5;
////	ModifyBox_Old(tbox, tc);
////	DstCenterX = tbox.x + tbox.w * 0.5;
////	DstCenterY = tbox.y + tbox.h * 0.5; 
////}
////
////void CHiBoostNodeContextConfig::GetStdBoxForNodeInstance(
////	double& DstCenterX, double& DstCenterY,
////	const CHiBoostNodeInstanceBoxSet* pInstanceBoxSet, int NodeIndex,
////	double InversedScaleX, double InversedScaleY)
////{
////	double cx, cy;
////	pInstanceBoxSet->ComputeNodeBoundingBoxCenter(cx, cy, NodeIndex);
////	GetStdBoxForNodeInstance(DstCenterX, DstCenterY, cx, cy, NodeIndex, InversedScaleX, InversedScaleY);
////}
//
//void CHiBoostNodeContextConfig::ModifyBox_New(CRectBox<double>& DstBox, double x, double y, double inference_scale, const CNode& Data)
//{
//	DstBox.w = Data.Context_W * inference_scale;
//	DstBox.h = Data.Context_H * inference_scale;
//	DstBox.x = x - DstBox.w * Data.xOffset;
//	DstBox.y = y - DstBox.h * Data.yOffset;
//}
//
//void CHiBoostNodeContextConfig::InverseModifyBox_New(double& DstX, double& DstY, double& DstInferenceScale, const CRectBox<double>& SrcBox, const CNode& Data)
//{
//	DstX = SrcBox.x + SrcBox.w * Data.xOffset;
//	DstY = SrcBox.y + SrcBox.h * Data.yOffset;
//	double inference_scale_x = SrcBox.w / Data.Context_W;
//	double inference_scale_y = SrcBox.h / Data.Context_H;
//	DstInferenceScale = sqrt(inference_scale_x * inference_scale_y);
//}
//
//void CHiBoostNodeContextConfig::GetContextBoxForNodeInstance(CRectBox<double>& DstBox, double x, double y, double inference_scale) const
//{
//	ModifyBox_New(DstBox, x, y, inference_scale, GlobalObject);
//}
//
//void CHiBoostNodeContextConfig::GetContextBoxForNodeInstance(CRectBox<double>& DstBox, double x, double y, double inference_scale, int NodeIndex) const
//{
//	ModifyBox_New(DstBox, x, y, inference_scale, GetDataForNode(NodeIndex));
//}
//
//void CHiBoostNodeContextConfig::GetNodeInstanceByContextBox(
//	double& DstX, double& DstY, double& DstImagePyramidLayerScale,
//	const CRectBox<double>& SrcBox, int NodeIndex
//	) const
//{
//	const CNode& Data = GetDataForNode(NodeIndex);
//	InverseModifyBox_New(DstX, DstY, DstImagePyramidLayerScale, SrcBox, Data);
//	DstImagePyramidLayerScale = 1.0 / DstImagePyramidLayerScale;
//}
//
//void CHiBoostNodeContextConfig::GetNodeInstanceByContextBox(
//	double& DstX, double& DstY, double& DstImagePyramidLayerScale, 
//	const CImagePyramidPosition& ipp, int NodeIndex
//	) const
//{
//	const CNode& Data = GetDataForNode(NodeIndex);
//	CRectBox<double> dBox;
//	dBox.w = Data.Context_W / ipp.xScale;
//	dBox.h = Data.Context_H / ipp.yScale;
//	dBox.x = ipp.xOld - dBox.w * 0.5;
//	dBox.y = ipp.yOld - dBox.h * 0.5;
//	InverseModifyBox_New(DstX, DstY, DstImagePyramidLayerScale, dBox, Data);
//	DstImagePyramidLayerScale = 1.0 / DstImagePyramidLayerScale;
//}
//
////void CHiBoostNodeContextConfig::ModifyBox_Old(CRectBox<double>& DstBox, const CNode& Data)
////{
////	DstBox.x += DstBox.w * (0.5 - Data.xOffset);
////	DstBox.y += DstBox.h * (0.5 - Data.yOffset);
////	DstBox.x -= DstBox.w * 0.5 * (Data.xScale - 1.0);
////	DstBox.y -= DstBox.h * 0.5 * (Data.yScale - 1.0);
////	DstBox.w *= Data.xScale;
////	DstBox.h *= Data.yScale;
////}
////
////void CHiBoostNodeContextConfig::GetRealBoxForNodeInstance(CRectBox<double>& DstBox, const CHiBoostNodeInstanceBoxSet* pInstanceBoxSet) const
////{
////	DstBox = pInstanceBoxSet->All_BoundingBox;
////	ModifyBox_Old(DstBox, GlobalObject);
////}
////
////void CHiBoostNodeContextConfig::GetRealBoxForNodeInstance(CRectBox<double>& DstBox, const CHiBoostNodeInstanceBoxSet* pInstanceBoxSet, int NodeIndex) const
////{
////	pInstanceBoxSet->ComputeNodeBoundingBox(DstBox, NodeIndex);
////	ModifyBox_Old(DstBox, GetDataForNode(NodeIndex));
////}

